package com.common.base.utils

import android.annotation.SuppressLint
import android.app.DownloadManager
import android.content.ActivityNotFoundException
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.database.ContentObserver
import android.database.Cursor
import android.net.Uri
import android.os.Environment
import android.os.Handler
import android.os.Looper
import android.provider.Settings

/**
 * 作者：sosou
 * <p>
 * 版本：1.0
 * <p>
 * 创建日期：2022/8/29
 * <p>
 * 描述：将下载功能封装在这个类
 * <p>
 * 修订历史：
 */
class DownloadServer(val mContext: Context?) {

    companion object {
        //下载的URI
        val CONTENT_URI: Uri = Uri.parse("content://downloads/my_downloads")
    }

    //下载管理器
    private val mManager = mContext?.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager?
    //监听下载的进度
    private val mDownloadContentObserver = DownloadObserver()


    //当前下载的ID号
    var mId: Long = -1

    //下载地址
    lateinit var mUrl: String
    //下载名
    lateinit var mName: String
    //下载中提示用户的标题文字
    lateinit var mTitle: String
    //下载中提示用户的描述文字
    lateinit var mDescription: String
    //监听回调，外部使用它来获得当前下载的进度已经状态
    lateinit var mOnDownloadListener: OnDownloadListener

    //注册监听
    fun registerContentObserver() {
        mContext?.contentResolver?.registerContentObserver(
                CONTENT_URI, true, mDownloadContentObserver)
    }

    //移除监听
    fun unregisterContentObserver() {
        mContext?.contentResolver?.unregisterContentObserver(mDownloadContentObserver)
    }

    //这种好处就是可以监听到下载进度、失败、完成
    //（第一种模式：内容观察者）
    inner class DownloadObserver : ContentObserver(Handler(Looper.getMainLooper())) {
        override fun onChange(selfChange: Boolean) {
            super.onChange(selfChange)
            val bytesAndStatus = getBytesAndStatus(mId)
            val currentSize = bytesAndStatus[0]//当前大小
            val totalSize = bytesAndStatus[1]//总大小
            val status = bytesAndStatus[2]//下载状态
            mOnDownloadListener.onDownload(currentSize, totalSize, status)
        }
    }

    //这个貌似只能监听完成和失败
    //（第二种模式：系统广播）
    inner class DownloadReceiver : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
            //下载完成的回调
            if (intent.action == DownloadManager.ACTION_DOWNLOAD_COMPLETE) {
                //下载的ID
                val id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1)


            } else if (intent.action == DownloadManager.ACTION_NOTIFICATION_CLICKED) {
                //点击了通知栏的回调
                // DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
                //获取所有下载任务Ids组
                //long[] ids = intent.getLongArrayExtra(DownloadManager.EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS);
                ////点击通知栏取消所有下载
                //manager.remove(ids);
                //Toast.makeText(context, "下载任务已取消", Toast.LENGTH_SHORT).show();
                //处理 如果还未完成下载，用户点击Notification ，跳转到下载中心
                val viewDownloadIntent = Intent(DownloadManager.ACTION_VIEW_DOWNLOADS)
                viewDownloadIntent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
                context.startActivity(viewDownloadIntent)
            }
        }
    }

    //监听回调，外部使用它来获得当前下载的进度已经状态
    interface OnDownloadListener {
        fun onDownload(currentSize: Long?, totalSize: Long?, status: Long?)
    }

    //获得下载的进度
    @SuppressLint("Range")
    private fun getBytesAndStatus(downloadId: Long): LongArray {
        val bytesAndStatus = longArrayOf(-1, -1, 0)
        val query = DownloadManager.Query().setFilterById(downloadId)
        var c: Cursor? = null
        try {
            c = mManager?.query(query)
            if (c != null && c.moveToFirst()) {
                bytesAndStatus[0] = c.getLong(c.getColumnIndexOrThrow(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR))
                bytesAndStatus[1] = c.getLong(c.getColumnIndexOrThrow(DownloadManager.COLUMN_TOTAL_SIZE_BYTES))
                bytesAndStatus[2] = c.getLong(c.getColumnIndex(DownloadManager.COLUMN_STATUS))
            }
        } finally {
            c?.close()
        }
        return bytesAndStatus
    }

    fun getUriForDownloadedFile(): Uri? {
        return mManager?.getUriForDownloadedFile(mId)
    }

    /**
     * 开始下载
     */
    fun start(visibility: Int = DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED, destinationUri: Uri? = null) {
        //解析地址
        val uri = Uri.parse(mUrl)
        //下载请求
        val req = DownloadManager.Request(uri)
        //设置允许使用的网络类型，这里是移动网络和wifi都可以
        req.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE or DownloadManager.Request.NETWORK_WIFI)
        //下载中和下载完后都显示通知栏
        req.setNotificationVisibility(visibility)

        //设置文件的保存的位置[三种方式]
        // 第一种 file:///storage/emulated/0/Android/data/your-package/files/Download/update.apk
        //第二种 file:///storage/emulated/0/Download/update.apk
//        req.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "update.apk")
        //第三种 自定义文件路径
        if (destinationUri != null) {
            req.setDestinationUri(destinationUri)
        } else {
            req.setDestinationInExternalFilesDir(mContext, Environment.DIRECTORY_DOWNLOADS, mName)
        }

        //禁止发出通知，既后台下载
//        req.setShowRunningNotification(false);
        //通知栏标题
        req.setTitle(mTitle)
        //通知栏描述信息
        req.setDescription(mDescription)
        //设置类型为.apk
        req.setMimeType("application/vnd.android.package-archive")
        // 设置为可被媒体扫描器找到
        req.allowScanningByMediaScanner()
        // 设置为可见和可管理
        req.setVisibleInDownloadsUi(true)

        mId = try {
            mManager?.enqueue(req) ?: -1
        } catch (e: Exception) {
            -1
        }
    }


    /**
     * 可能会出错Cannot update URI: content://downloads/my_downloads/-1
     * 检查下载管理器是否被禁用
     */
    fun checkDownloadManagerEnable(): Boolean {
        try {
            val state = mContext?.packageManager?.getApplicationEnabledSetting("com.android.providers.downloads")
            if (state == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
                    || state == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER
                    || state == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
                val packageName = "com.android.providers.downloads"
                try {
                    val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
                    intent.data = Uri.parse("package:$packageName")
                    mContext?.startActivity(intent)
                } catch (e: ActivityNotFoundException) {
                    e.printStackTrace()
                    val intent = Intent(Settings.ACTION_MANAGE_APPLICATIONS_SETTINGS)
                    mContext?.startActivity(intent)
                }
                return false
            }
        } catch (e: Exception) {
            e.printStackTrace()
            return false
        }
        return true
    }


    /**
     * 下载前先移除前一个任务，防止重复下载
     *
     * @param downloadId
     */
    fun clear(downloadId: Long) {
        try {
            mManager?.remove(downloadId)
        } catch (ex: IllegalArgumentException) {
            ex.printStackTrace()
        }
    }

}